#ifndef _MIDEF_HEADER
#define _MIDEF_HEADER

/*
    http://sources.redhat.com/gdb/current/onlinedocs/gdb_25.html

    GDB /mi Specification

    output ==>
        ( out-of-band-record )* [ result-record ] "(gdb)" nl
    result-record ==>
        [ token ] "^" result-class ( "," result )* nl
    out-of-band-record ==>
        async-record | stream-record
    async-record ==>
        exec-async-output | status-async-output | notify-async-output
    exec-async-output ==>
        [ token ] "*" async-output
    status-async-output ==>
        [ token ] "+" async-output
    notify-async-output ==>
        [ token ] "=" async-output
    async-output ==>
        async-class ( "," result )* nl
    result-class ==>
        "done" | "running" | "connected" | "error" | "exit"
    async-class ==>
        "stopped" | others (where others will be added depending on the needs--this is still in development).
    result ==>
        variable "=" value
    variable ==>
        string
    value ==>
        const | tuple | list
    const ==>
        c-string
    tuple ==>
        "{}" | "{" result ( "," result )* "}"
    list ==>
        "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
    stream-record ==>
        console-stream-output | target-stream-output | log-stream-output
    console-stream-output ==>
        "~" c-string
    target-stream-output ==>
        "@" c-string
    log-stream-output ==>
        "&" c-string
    nl ==>
        CR | CR-LF
    token ==>
        any sequence of digits.
*/

#ifndef _DEBUG
#define dbg_print(s)
#else
#include <stdio.h>
#define dbg_print(s)    printf(s)
#endif

struct tagMIResult;
struct tagMIValue;
struct tagMIList;

enum MIValueType { VT_CONST, VT_TUPLE, VT_LIST };
enum MIAsyncType { EXEC, STATUS, NOTIFY };
enum MIAsyncClass    { STOPPED, OTHER };
enum MIStreamType { CONSOLE, TARGET, LOG };
enum MIOutOfBandRecordType { ASYNC, STREAM };
enum MIResultClass { RC_DONE, RC_RUNNING, RC_CONNECTED, RC_ERROR, RC_EXIT };
enum MIListType { EMPTY, VALUE, RESULT };

typedef int    MIToken;
typedef char * MIString;
typedef MIString MICString;


typedef struct tagMIResult
{
    MIString            m_variable;
    struct tagMIValue    * m_pValue;
    struct tagMIResult    * m_pNext;
}MIResult;

typedef struct tagMIValue
{
    MIValueType                m_type;
    union
    {
        MIString            m_string;
        struct tagMIResult    * m_pResult;
        struct tagMIList    * m_pList;
    };
    struct tagMIValue        * m_pNext;
}MIValue;

typedef struct tagMIList
{
    MIListType                m_type;
    union
    {
        struct tagMIResult    * m_pResult;
        struct tagMIValue    * m_pValue;
    };
}MIList;

typedef struct tagMIAsyncRecord
{
    MIAsyncType                m_type;
    MIToken                    m_token;
    MIAsyncClass            m_class;
    MIResult                * m_pResult;
}MIAsyncRecord;

typedef struct tagMIStreamRecord
{
    MIStreamType            m_type;
    MICString                m_string;
}MIStreamRecord;

typedef struct tagMIOutOfBandRecord
{
    MIOutOfBandRecordType    m_type;
    union
    {
        MIAsyncRecord        * m_pAsyncRecord;
        MIStreamRecord        * m_pStreamRecord;
    };
    struct tagMIOutOfBandRecord    * m_pNext;
}MIOutOfBandRecord;

typedef struct tagMIResultRecord
{
    MIResultClass            m_class;
    MIToken                    m_token;
    MIResult                * m_pResult;
}MIResultRecord;

typedef struct tagMIGDBOutput
{
    MIOutOfBandRecord    * m_pOutOfBandRecord;
    MIResultRecord        * m_pResultRecord;
}MIGDBOutput;

MIGDBOutput *    ParseMIOutput (const char * output);
void            ReleaseMIOutput (MIGDBOutput * output);
void            ReleaseMIResultRecord (MIResultRecord * record);
MIValue *        GetMIValue (MIResult * result, MIString variable);
MIString        ConvertCString (MICString cstr);

#endif // _MIDEF_HEADER
